home *** CD-ROM | disk | FTP | other *** search
- /* The routines in this file are copyright (c) 1987 by Helene (Lee) Taran.
- * Permission is granted for use and free distribution as long as the
- * original author's name is included with the code.
- */
-
- /*
- * Reformatted, and modified to compile without warnings and errors
- * under SAS/C -6.5x by gduncan@philips.oz.au (GMD). This included
- * proto generation, renaming of some literals to avoid name collisions,
- * and Amiga Version string (also displayed in Title bar).
- * No original version number, this version arbitrarily named 1.1.
- * - otherwise no functional changes.
- * GMD - Sep 94
- */
-
- #include "all.h"
-
- LAYER_INFO *PopUp_LayerInfo;
- TEXTFONT *menufont;
-
- /* User should call Init_MenuPackage() before trying to pop up any
- * menus. Will return TRUE if the package has been initialized correctly.
- * Do not attempt to use this package if this initialization routine
- * returns FALSE.
- */
-
- BOOL
- Init_MenuPackage ()
- {
- static TEXTATTR MenuFont =
- {(UBYTE *) "topaz.font", 8, 0, 0};
-
- if (!(menufont = OpenFont (&MenuFont)))
- {
- fprintf (stderr, "sorry couldn't find topaz eight for menu font]\n");
- return (FALSE);
- }
- if (!(PopUp_LayerInfo = (LAYER_INFO *) NewLayerInfo ()))
- {
- fprintf (stderr, "sorry, couldn't allocate a layer info structure\n");
- return (FALSE);
- }
- return (TRUE);
- }
-
- /* The user should call Close_MenuPackage before exiting their program
- * to ensure that the menu package releases any memory that it
- * has allocated for its own use.
- */
-
- void
- Close_MenuPackage ()
- {
- CloseFont (menufont);
- if (PopUp_LayerInfo != NULL)
- DisposeLayerInfo (PopUp_LayerInfo);
-
- }
-
- BOOL
- Init_PopUp_Menu (menu)
- SPL_POPUP_MENU *menu;
- {
-
- SPL_POPUP_ITEM *item;
- int longest = 0;
- int total_height = 0;
- int i;
-
- if (menu == NULL)
- return (FALSE);
- item = menu->first_item;
- while (item != NULL)
- {
- /* note: bad things may happen if you allocate an empty string for
- * your item text.
- */
-
- i = strlen (item->text); /* GMD ; extract to deconfuse compiler */
-
- item->width = MAX (item->width, FONT_WIDTH * i);
- item->left = MAX (0, item->left);
- longest = MAX (longest, (item->width + item->left));
- item->height = MAX (item->height, FONT_HEIGHT);
- item->top = MAX (0, item->top);
- total_height += (item->height + item->top);
- /* re-initialize item-top to be the top relative to the menu top */
- item->top = (total_height - item->height);
- item = item->next;
- }
- menu->height = total_height + 1;
- menu->width = MAX (menu->width, longest);
-
- /* initialize a bitmap the same size as the required menu image */
- /* initialize a raster port to facillitate drawing into the bitmap */
- InitBitMap (&(menu->bitmap), menu->depth, menu->width, menu->height);
- InitRastPort (&(menu->rp));
-
- #if 1
- SetFont (&menu->rp, menufont); /*GMD */
- #else
- SetFont (menu->rp, menufont);
- #endif
-
- for (i = 0; i < menu->depth; i++)
- if (!(menu->bitmap.Planes[i] = (PLANEPTR)
- AllocRaster (menu->width, menu->height)))
- {
- Dispose_PopUp (menu);
- return (FALSE);
- }
- menu->rp.BitMap = &(menu->bitmap);
- menu->cr.BitMap = &(menu->bitmap);
-
- /* draw the menu outline and background color into its own bitmap */
- SetDrMd (&(menu->rp), JAM1);
- SetAPen (&(menu->rp), menu->area_color);
- SetOPen (&(menu->rp), menu->outline_color);
-
- RectFill (&(menu->rp), 0, 0, menu->width - 1, menu->height - 1);
- BNDRYOFF (&(menu->rp)); /* turn off the raster port outlining */
-
- item = menu->first_item;
-
- /* Now, draw each menu item */
- while (item != NULL)
- {
- SetAPen (&(menu->rp), item->color);
- Move (&(menu->rp), item->left, item->top + FONT_BASELINE);
- Text (&(menu->rp), item->text, strlen (item->text));
- item = item->next;
- }
- return (TRUE);
- }
-
- /* SelectItem : activates the item located at <x,y>. Assumes the <menu>
- * is currently active and thus, menu->left and menu->top should represent
- * the menu's current top,left corner. If there is an item located
- * at <x,y> within the menu, then it is made 'active' ...this means
- * that the item becomes menu->active_item and is highlighted. The
- * old menu->active_item, if any, is deselected. Note: if you're using
- * a GIMMEZEROZERO window you'll have to fiddle with the x,y coordinates.
- */
-
- void
- SelectItem (menu, Window)
- SPL_POPUP_MENU *menu;
- WINDOW *Window;
- {
- SPL_POPUP_ITEM *item;
-
- SHORT x = Window->MouseX + Window->LeftEdge;
- SHORT y = Window->MouseY + Window->TopEdge;
-
- item = menu->first_item;
- x -= menu->left;
- y -= menu->top;
- if ((x >= 0) && (x < menu->width) && (y >= 0) && (y < menu->height))
- while (item != NULL)
- {
- if ((y >= item->top - 1) && (y < item->top - 1 + item->height))
- break; /* we found an active item {yeah yeah...bad style, i know...} */
- else
- item = item->next;
- }
- else
- item = NULL; /* mouse isn't on menu */
-
- if (menu->active_item != item)
- { /* deselect previously active item */
- ComplementItem (menu, menu->active_item, Window);
- ComplementItem (menu, item, Window);
- }
- menu->active_item = item;
- }
-
-
-
-
- /* ComplementItem : complements the given menu item area. Assumes that
- * the <menu> is currently being displayed and thus,the current menu->left
- * and menu->top represent the current coordinates of the menu's top,left
- * corner. Assumes the <item> is an popup_item that belongs to <menu>
- * and that its left/top offsets have been initialized.
- */
-
- void
- ComplementItem (menu, item, Window)
- SPL_POPUP_MENU *menu;
- SPL_POPUP_ITEM *item;
- WINDOW *Window;
- {
- BYTE old_mode = Window->WScreen->RastPort.DrawMode;
-
- if (item == NULL)
- return; /* do nothing */
- SetDrMd (&(Window->WScreen->RastPort), COMPLEMENT);
- RectFill (&(Window->WScreen->RastPort), menu->left,
- menu->top + item->top - 1,
- menu->left + menu->width - 1,
- menu->top + item->top + item->height - 2);
- SetDrMd (&(Window->WScreen->RastPort), (int) old_mode);
- }
-
- /* PopUp : this is one of those 'do everything' type of functions. It
- * displays the <menu> in the window given its upper left hand
- * coordinates <left,top>. It tracks the user's mouse movements,
- * highlighting the currently active item until the user deselects
- * the menu by releasing the mouse's select button, at which time,
- * this function will remove the menu from the display. Returns the
- * selection_id of the item that was active when the user releases
- * the select button. Returns 0 if nothing was selected.
- * Assumes that the <menu> has been initialized by a call to
- * Init_SPL_POPUP_MENU and that the user has requested ReportMouse for the
- * Window in question (ReportMouse makes sure that the Window's MouseX and
- * MouseY coordinates are kept up to date).
- */
- int
- PopUp (menu, Window)
- SPL_POPUP_MENU *menu;
- WINDOW *Window;
- {
- ULONG oldflags;
- SHORT left, top;
-
- left = Window->MouseX;
- top = Window->MouseY;
- if (!Inside_Window (left, top, Window))
- return (OUTSIDE_WINDOW);
-
- if ((menu->width <= Window->Width) && (left + menu->width > Window->Width))
- left += Window->Width - (left + menu->width);
-
- if ((menu->height <= Window->Height) && (top + menu->height > Window->Height))
- top += Window->Height - (top + menu->height);
-
- LockLayers (PopUp_LayerInfo);
-
- /* SwapBits...() requires that the clipping rectangle's bounds are given
- * with respect to the screen's 0,0 coordinate but mouse movements
- * are reported to the Window and are given in terms of the window's
- * coordinate system so...sLeft and sTop represent the adjustment of
- * the Window's coordinates to match the screen's coordinates.
- * Note: if you're using a GIMMEZEROZERO window, you'll have to muck
- * with the left,top coordinates to get the complementing to work.
- */
- left = (left + Window->LeftEdge) & 0xfff0;
- top = top + Window->TopEdge;
-
- menu->cr.bounds.MinX = left;
- menu->cr.bounds.MinY = top;
- menu->cr.bounds.MaxX = left + menu->width - 1;
- menu->cr.bounds.MaxY = top + menu->height - 1;
- SwapBitsRastPortClipRect (Window->RPort, &(menu->cr));
-
- menu->left = left;
- menu->top = top;
- SelectItem (menu, Window);
- oldflags = Window->IDCMPFlags;
- ModifyIDCMP (Window, oldflags | MOUSEMOVE);
-
- while (1) /* wait for the user to select an item and deselect the menu */
- {
- INTUIMESSAGE msg, *message;
- int MouseMoved = FALSE;
-
- Wait (1 << Window->UserPort->mp_SigBit);
- while (message = (INTUIMESSAGE *) GetMsg (Window->UserPort))
- {
- msg = *message; /* make a backup copy of message */
- ReplyMsg ((MESSAGE *) message); /* reply immediately to prevent deadlock */
- if (msg.Class == MOUSEMOVE)
- /* just keep track of the fact that the mouse moved */
- MouseMoved = TRUE;
- else if ((msg.Class == MOUSEBUTTONS) && (msg.Code == menu->deactivate))
- {
- /* user has deselected the menu */
- ModifyIDCMP (Window, oldflags); /* restore idcmp flags */
- SelectItem (menu, Window);
- SwapBitsRastPortClipRect (Window->RPort, &(menu->cr));
- UnlockLayers (PopUp_LayerInfo);
- if (menu->active_item != NULL)
- return (menu->active_item->selection_id);
- else
- return (NOITEM_SELECTED);
- } /* end of deselection routine */
- }
- /*
- * at this point the message queue should be empty so the mouse
- * has stopped for the moment.
- */
- if (MouseMoved)
- SelectItem (menu, Window);
- }
- }
-
- void
- Dispose_PopUp (menu)
- SPL_POPUP_MENU *menu;
- {
- int i;
- for (i = 0; i < menu->depth; i++)
- if (menu->bitmap.Planes[i] != NULL)
- FreeRaster (menu->bitmap.Planes[i], menu->width, menu->height);
- }
- /*--*/
-
- /*--*/
-